package service

import (
	"boy-go/modules/system/model"
	"boy-go/modules/system/repository"
	"boy-go/modules/system/vo"
	"boy-go/pkg/domain"
	"boy-go/pkg/security"
	"github.com/jinzhu/copier"
)

func NewSysDeptService() SysDeptService {
	return &sysDeptService{
		SysDeptRepo: repository.NewSysDeptRepository(),
		SysRoleRepo: repository.NewSysRoleRepository(),
	}
}

type sysDeptService struct {
	SysDeptRepo *repository.SysDeptRepository
	SysRoleRepo *repository.SysRoleRepository
}

// GetById 根据id获取配置信息
func (s *sysDeptService) GetById(deptId int64) (*vo.SysDeptModel, error) {
	m, err := s.SysDeptRepo.GetById(deptId)
	if err != nil {
		return nil, err
	}
	rsp := new(vo.SysDeptModel)
	if err := copier.Copy(rsp, m); err != nil {
		return nil, err
	}
	return rsp, nil
}

// List 获取部门表列表
func (s *sysDeptService) List(req *vo.QuerySysDeptReq) (*vo.ListSysDeptRsp, error) {
	list, total, err := s.SysDeptRepo.List(req, nil)
	if err != nil {
		return nil, err
	}
	itemList := make([]*vo.SysDeptModel, 0)
	for _, v := range list {
		item := new(vo.SysDeptModel)
		if err := copier.Copy(item, &v); err != nil {
			continue
		}
		itemList = append(itemList, item)
	}
	return &vo.ListSysDeptRsp{
		List:  itemList,
		Total: total,
	}, nil
}

// Add 添加部门表
func (s *sysDeptService) Add(req *vo.AddSysDeptReq) (*vo.AddSysDeptRsp, error) {
	m := new(model.SysDept)
	err := copier.Copy(m, req)
	if err != nil {
		return nil, err
	}
	if err := s.SysDeptRepo.Save(m); err != nil {
		return nil, err
	}
	return &vo.AddSysDeptRsp{
		DeptId: m.DeptId,
	}, nil
}

// Edit 修改部门表
func (s *sysDeptService) Edit(req *vo.EditSysDeptReq) (*vo.EditSysDeptRsp, error) {
	m := new(model.SysDept)
	err := copier.Copy(m, req)
	if err != nil {
		return nil, err
	}
	if err := s.SysDeptRepo.Update(m); err != nil {
		return nil, err
	}
	return &vo.EditSysDeptRsp{
		DeptId: m.DeptId,
	}, nil
}

// Del 删除部门表
func (s *sysDeptService) Del(deptId int64) error {
	return s.SysDeptRepo.Delete(deptId)
}

func (s *sysDeptService) BatchDel(ids []string) error {
	return s.SysDeptRepo.BatchDelete(ids)
}

// 根据角色ID查询部门树信息
func (s *sysDeptService) SelectDeptListByRoleId(roleId int64) []*int64 {
	role, err := s.SysRoleRepo.GetById(roleId)
	if err != nil {
		return nil
	}
	isDeptCheckStrictly := false
	if role.DeptCheckStrictly != nil && *role.MenuCheckStrictly == true {
		isDeptCheckStrictly = true
	}
	return s.SysDeptRepo.SelectDeptListByRoleId(roleId, isDeptCheckStrictly)
}

func (s *sysDeptService) SelectDeptTreeList(query *vo.QuerySysDeptReq) []*domain.TreeSelect {
	list, _, err := s.SysDeptRepo.List(query, nil)
	if err != nil {
		return nil
	}
	return s.BuildDeptTreeSelect(list)
}
func (s *sysDeptService) BuildDeptTree(depts []*model.SysDept) []*model.SysDept {
	var returnList = make([]*model.SysDept, 0)
	tempMap := make(map[int64]*model.SysDept)
	// 提取所有 deptId 到 map 中用于快速查找
	for _, dept := range depts {
		tempMap[dept.DeptId] = dept
	}
	// 遍历所有部门，找出顶级节点
	for _, dept := range depts {
		prentId := *dept.ParentId
		_, exists := tempMap[prentId]
		if exists == false {
			s.recursionFn(depts, dept)
			returnList = append(returnList, dept)
		}
	}
	// 如果没有顶级节点，则返回原始列表
	if len(returnList) == 0 {
		returnList = depts
	}
	return returnList
}
func (s *sysDeptService) BuildDeptTreeSelect(depts []*model.SysDept) []*domain.TreeSelect {
	deptTrees := s.BuildDeptTree(depts)
	var treeSelects []*domain.TreeSelect
	for _, dept := range deptTrees {
		treeSelects = append(treeSelects, s.convertToTreeSelect(dept))
	}
	return treeSelects
}

// 递归转换 SysDept -> TreeSelect
func (s *sysDeptService) convertToTreeSelect(dept *model.SysDept) *domain.TreeSelect {
	ts := &domain.TreeSelect{
		ID:    dept.DeptId,
		Label: *dept.DeptName,
	}
	for _, child := range dept.Children {
		ts.Children = append(ts.Children, s.convertToTreeSelect(child))
	}
	return ts
}

// 递归列表
func (s *sysDeptService) recursionFn(list []*model.SysDept, t *model.SysDept) {
	// 得到子节点列表
	childList := s.getChildList(list, t)
	t.Children = childList
	for _, tChild := range childList {
		if s.hasChild(list, tChild) {
			s.recursionFn(list, tChild)
		}
	}
}

// getChildList 获取当前节点的所有直接子节点
func (s *sysDeptService) getChildList(list []*model.SysDept, t *model.SysDept) []*model.SysDept {
	var tlist []*model.SysDept
	for _, node := range list {
		if node.ParentId != nil && *node.ParentId == t.DeptId {
			tlist = append(tlist, node)
		}
	}
	return tlist
}

// hasChild 判断当前节点是否有子节点
func (s *sysDeptService) hasChild(list []*model.SysDept, t *model.SysDept) bool {
	if len(s.getChildList(list, t)) > 0 {
		return true
	}
	return false
}

func (s *sysDeptService) CheckDeptDataScope(deptId *int64) error {
	loginUser := security.GetLoginUser()
	if !model.IsAdmin(&loginUser.UserId) && deptId != nil {
		deptsRsp, err := s.List(&vo.QuerySysDeptReq{DeptId: *deptId})
		if err != nil || deptsRsp.Total <= 0 {
			return err
		}
	}
	return nil
}
